package com.enation.app.javashop.core.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.enation.app.javashop.core.base.message.GoodsChangeMsg;
import com.enation.app.javashop.core.base.message.ShetuanChangeMsg;
import com.enation.app.javashop.core.base.rabbitmq.AmqpExchange;
import com.enation.app.javashop.core.goods.model.dos.GoodsDO;
import com.enation.app.javashop.core.goods.model.vo.GoodsSkuVO;
import com.enation.app.javashop.core.goods.service.GoodsSkuManager;
import com.enation.app.javashop.core.promotion.shetuan.model.dos.ShetuanGoodsDO;
import com.enation.app.javashop.core.promotion.shetuan.model.enums.ShetuanGoodsStatusEnum;
import com.enation.app.javashop.core.promotion.tool.support.SkuNameUtil;
import com.enation.app.javashop.core.shop.model.dos.ShopCatDO;
import com.enation.app.javashop.core.shop.model.vo.ShopCatItem;
import com.enation.app.javashop.core.shop.service.ShopCatManager;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.security.model.Seller;
import com.enation.app.javashop.framework.util.BeanUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: zhou
 * @Date: 2020/10/20
 * @Description: 导入社团商品
 */
@Slf4j
public class ShetuanGoodsDataListener extends AnalysisEventListener<ExcelShetuanGoodsVO> {
    /**
     * 每隔20条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 10;
    private List<ExcelShetuanGoodsVO> importList = new ArrayList<>();
    public static List<ExcelShetuanGoodsVO> errorImportList = new ArrayList<>();

    private AmqpTemplate amqpTemplate;

    private DaoSupport daoSupport;

    private GoodsSkuManager goodsSkuManager;

    private ShopCatManager shopCatManager;

    private JdbcTemplate jdbcTemplate;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     */
    public ShetuanGoodsDataListener(GoodsSkuManager goodsSkuManager, ShopCatManager shopCatManager,
                                    AmqpTemplate amqpTemplate, DaoSupport daoSupport, JdbcTemplate jdbcTemplate) {
        this.amqpTemplate = amqpTemplate;
        this.daoSupport = daoSupport;
        this.goodsSkuManager = goodsSkuManager;
        this.shopCatManager = shopCatManager;
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void invoke(ExcelShetuanGoodsVO importShetuanGoods, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(importShetuanGoods));
        importList.add(importShetuanGoods);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (importList.size() >= BATCH_COUNT) {
            updateData();
            // 存储完成清理 list
            importList.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        updateData();
        log.info("所有数据解析完成！");
    }

    private void updateData() {
        log.info("{}条数据，开始存储数据库！", importList.size());

        if (CollectionUtils.isNotEmpty(importList)) {
            // 社团ID
            Integer shetuanId = importList.get(0).getShetuanId();

            //1、查询社团活动中的所有已上架的商品
            String sql = "select * from es_shetuan_goods  where status!=" + ShetuanGoodsStatusEnum.DELETE.getIndex() + " and shetuan_id =?";
            List<ShetuanGoodsDO> shetuanGoodsDOList = daoSupport.queryForList(sql, ShetuanGoodsDO.class, shetuanId);
            Map<Integer, ShetuanGoodsDO> shetuanGoodsDOMap = shetuanGoodsDOList.stream().collect(Collectors.toMap(ShetuanGoodsDO::getSkuId, Function.identity(), (oldValue, newValue) -> newValue));

            //需要更新索引信息的社团商品
            ShetuanChangeMsg shetuanChangeMsg = new ShetuanChangeMsg();
            shetuanChangeMsg.setShetuanId(shetuanId);
            List<Integer> skuIdsList = new ArrayList<>();

            //需要新增的商品
            List<ShetuanGoodsDO> needInsertGoodsDOList = new ArrayList<>();
            //需要更新的商品
            List<ShetuanGoodsDO> updateGoodsDOList = new ArrayList<>();
            List<Object[]> batchArgs = new ArrayList<>();

            Seller seller = UserContext.getSeller();
            for (ExcelShetuanGoodsVO goodsImport : importList) {
                //如果没有社团ID不保存
                if (goodsImport.getShetuanId() != null) {
                    //2、判断该社团活动中是否已经存在这个商品
                    if (shetuanGoodsDOMap.get(goodsImport.getSkuId()) == null) {
                        //团购活动中新增商品
                        ShetuanGoodsDO shetuanGoodsDO = new ShetuanGoodsDO();
                        BeanUtils.copyProperties(goodsImport, shetuanGoodsDO);
                        shetuanGoodsDO.setSellerId(seller.getSellerId());
                        shetuanGoodsDO.setSellerName(seller.getSellerName());
                        //需要新增的社团商品
                        ShetuanGoodsDO needInsertShetuanGoodsDO = this.addFormatGoods(shetuanGoodsDO, goodsImport);
                        if (!ObjectUtils.isEmpty(needInsertShetuanGoodsDO)) {
                            needInsertGoodsDOList.add(needInsertShetuanGoodsDO);
                        } else {
                            errorImportList.add(goodsImport);
                            continue;
                        }
                    } else {
                        //需要更新的社团商品
                        ShetuanGoodsDO shetuanGoodsDO = this.updateFormatGoods(shetuanGoodsDOMap.get(goodsImport.getSkuId()), goodsImport);

                        if (shetuanGoodsDO != null) {
                            updateGoodsDOList.add(shetuanGoodsDO);
                        } else {
                            errorImportList.add(goodsImport);
                        }

                    }
                    skuIdsList.add(goodsImport.getSkuId());
                } else {
                    errorImportList.add(goodsImport);
                }
            }

            //批量添加社团商品
            if (CollectionUtils.isNotEmpty(needInsertGoodsDOList)) {
                this.daoSupport.batchInsert("es_shetuan_goods", shetuanGoodsDOList);

                List<Integer> goodsIds = needInsertGoodsDOList.stream().map(ShetuanGoodsDO::getGoodsId).collect(Collectors.toList());
                // 发送增加商品消息
                GoodsChangeMsg goodsChangeMsg = new GoodsChangeMsg(goodsIds.toArray(new Integer[goodsIds.size()]),
                        GoodsChangeMsg.ADD_OPERATION);
                this.amqpTemplate.convertAndSend(AmqpExchange.GOODS_CHANGE, AmqpExchange.GOODS_CHANGE + "_ROUTING", goodsChangeMsg);

            }

            //批量更新社团商品
            if (CollectionUtils.isNotEmpty(updateGoodsDOList)) {
                //subsidy_rate=?,
                String updateSql = "update es_shetuan_goods set priority = ?,cost =? , shetuan_price =?, visual_num=?,goods_num=?,limit_num=?,first_rate=?,second_rate=?, \n" +
                        "self_raising_rate=?,invite_rate=?,status=?,shop_cat_items=?,shop_cat_name=?,update_time=? where id=?";
                long updateTime = DateUtil.getDateline();
                this.jdbcTemplate.batchUpdate(updateSql, new BatchPreparedStatementSetter() {
                    @Override
                    public int getBatchSize() {
                        return updateGoodsDOList.size();
                    }

                    @Override
                    public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
                        ShetuanGoodsDO goodsDO = updateGoodsDOList.get(i);
                        preparedStatement.setDouble(1, goodsDO.getPriority());
                        preparedStatement.setDouble(2, goodsDO.getCost());
                        preparedStatement.setDouble(3, goodsDO.getShetuanPrice());
                        preparedStatement.setInt(4, goodsDO.getVisualNum());
                        preparedStatement.setInt(5, goodsDO.getGoodsNum());
                        preparedStatement.setInt(6, goodsDO.getLimitNum());
                        preparedStatement.setBigDecimal(7, BigDecimal.valueOf(goodsDO.getFirstRate()));
                        preparedStatement.setBigDecimal(8, BigDecimal.valueOf(goodsDO.getSecondRate()));
                        preparedStatement.setBigDecimal(9, BigDecimal.valueOf(goodsDO.getSelfRaisingRate()));
                        preparedStatement.setBigDecimal(10, BigDecimal.valueOf(goodsDO.getInviteRate()));
                        // 后面excel模板同步更新后放开并修改序列号
                        // preparedStatement.setBigDecimal(11, BigDecimal.valueOf(goodsDO.getSubsidyRate()));
                        preparedStatement.setInt(11, goodsDO.getStatus());
                        preparedStatement.setString(12, goodsDO.getShopCatItems());
                        preparedStatement.setString(13, goodsDO.getShopCatName());
                        preparedStatement.setLong(14, updateTime);
                        preparedStatement.setInt(15, goodsDO.getId());
                    }
                });
            }

            //更新sku索引
            if (!CollectionUtils.isEmpty(skuIdsList)) {
                shetuanChangeMsg.setSkuIds(skuIdsList);
                this.amqpTemplate.convertAndSend(AmqpExchange.SHETUAN_CHANGE, AmqpExchange.SHETUAN_CHANGE + "_ROUTING", shetuanChangeMsg);
            }


        }

    }

    //新增社团商品信息
    private ShetuanGoodsDO addFormatGoods(ShetuanGoodsDO shetuanGoodsDO, ExcelShetuanGoodsVO goodsImport) {
        // 查询商品库存
        GoodsSkuVO skuVO = goodsSkuManager.getSkuFromCache(shetuanGoodsDO.getSkuId());

        if (skuVO == null || skuVO.getIsGlobal() == null) {
            return null;
        }
        if (skuVO.getIsGlobal() != 1) {
            return null;
        }

        GoodsDO goodsDO = this.daoSupport.queryForObject(GoodsDO.class, skuVO.getGoodsId());
        if (goodsDO.getMarketEnable() == 0) {
            // 商品下架不处理
            return null;
        }

        // 默认使用商品总可用库存
        if (skuVO.getEnableQuantity() < 1) {
            return null;
        }

        if (goodsImport.getShetuanPrice() == null) {
            return null;
        }

        shetuanGoodsDO.setGoodsId(goodsDO.getGoodsId());
        shetuanGoodsDO.setGoodsName(goodsDO.getGoodsName() + " " + SkuNameUtil.createSkuName(skuVO.getSpecs()));
        shetuanGoodsDO.setSn(skuVO.getSn());
        shetuanGoodsDO.setVideoUrl(goodsDO.getVideoUrl());

        //社团商品上下架状态
        if (StringUtil.notEmpty(goodsImport.getShetuanGoodsStatusText())) {
            shetuanGoodsDO.setStatus(getShetunGoodsStatus(goodsImport.getShetuanGoodsStatusText()));
        }

        //设置商品分组信息
        if (StringUtil.notEmpty(goodsImport.getShopCatName())) {
            Map<String, String> map = getShetuanGoodsShopCat(shetuanGoodsDO, goodsImport.getShopCatName());
            if (map != null) {
                shetuanGoodsDO.setShopCatItems(map.get("shopCatItems"));
                shetuanGoodsDO.setShopCatName(map.get("shopCatName"));
            }
        } else {
            shetuanGoodsDO.setShopCatItems(null);
            shetuanGoodsDO.setShopCatName(null);
        }

        //参团数量
        Integer goodsNum = goodsImport.getGoodsNum();
        if (goodsNum != null && goodsNum < skuVO.getEnableQuantity() && goodsNum > 1) {
            shetuanGoodsDO.setGoodsNum(goodsNum);
        } else {
            shetuanGoodsDO.setGoodsNum(skuVO.getEnableQuantity());
        }

        //虚拟数量
        if (shetuanGoodsDO.getVisualNum() != null && shetuanGoodsDO.getVisualNum() > shetuanGoodsDO.getGoodsNum()) {
            shetuanGoodsDO.setVisualNum(shetuanGoodsDO.getGoodsNum() / 2);
        }
        shetuanGoodsDO.setBuyNum(0);

        shetuanGoodsDO.setOriginPrice(goodsDO.getMktprice());
        shetuanGoodsDO.setSalesPrice(skuVO.getPrice());
        shetuanGoodsDO.setThumbnail(skuVO.getThumbnail());

        return shetuanGoodsDO;
    }

    //判断哪些字段需要更新,批量更新
    private ShetuanGoodsDO updateFormatGoods(ShetuanGoodsDO shetuanGoodsDO, ExcelShetuanGoodsVO goodsImport) {
        if (goodsImport.getPriority() != null) {
            shetuanGoodsDO.setPriority(goodsImport.getPriority());
        } else if (shetuanGoodsDO.getPriority() == null) {
            return null;
        }
        if (goodsImport.getCost() != null) {
            shetuanGoodsDO.setCost(goodsImport.getCost());
        } else if (shetuanGoodsDO.getCost() == null) {
            return null;
        }
        if (goodsImport.getShetuanPrice() != null) {
            shetuanGoodsDO.setShetuanPrice(goodsImport.getShetuanPrice());
        } else if (shetuanGoodsDO.getShetuanPrice() == null) {
            return null;
        }
        if (goodsImport.getVisualNum() != null) {
            shetuanGoodsDO.setVisualNum(goodsImport.getVisualNum());
        } else if (shetuanGoodsDO.getVisualNum() == null) {
            return null;
        }

        Integer goodsNum = goodsImport.getGoodsNum();
        if (goodsNum != null && goodsNum > 0) {
            shetuanGoodsDO.setGoodsNum(goodsImport.getGoodsNum());
        } else if (shetuanGoodsDO.getGoodsNum() == null) {
            return null;
        }
        Integer limitNum = goodsImport.getLimitNum();
        if (limitNum != null && limitNum > 0 && limitNum < shetuanGoodsDO.getGoodsNum()) {
            shetuanGoodsDO.setLimitNum(goodsImport.getLimitNum());
        } else if (shetuanGoodsDO.getLimitNum() == null) {
            return null;
        }
        if (goodsImport.getFirstRate() != null) {
            shetuanGoodsDO.setFirstRate(goodsImport.getFirstRate());
        } else if (shetuanGoodsDO.getFirstRate() == null) {
            return null;
        }
        if (goodsImport.getSecondRate() != null) {
            shetuanGoodsDO.setSecondRate(goodsImport.getSecondRate());
        } else if (shetuanGoodsDO.getSecondRate() == null) {
            return null;
        }
        if (goodsImport.getSelfRaisingRate() != null) {
            shetuanGoodsDO.setSelfRaisingRate(goodsImport.getSelfRaisingRate());
        } else if (shetuanGoodsDO.getSelfRaisingRate() == null) {
            return null;
        }
        if (goodsImport.getInviteRate() != null) {
            shetuanGoodsDO.setInviteRate(goodsImport.getInviteRate());
        } else if (shetuanGoodsDO.getInviteRate() == null) {
            return null;
        }

        //社团商品上下架状态
        if (StringUtil.notEmpty(goodsImport.getShetuanGoodsStatusText())) {
            shetuanGoodsDO.setStatus(getShetunGoodsStatus(goodsImport.getShetuanGoodsStatusText()));
        } else if (shetuanGoodsDO.getShetuanPrice() == null) {
            return null;
        }

        //设置商品分组信息
        if (StringUtil.notEmpty(goodsImport.getShopCatName())) {
            Map<String, String> map = getShetuanGoodsShopCat(shetuanGoodsDO, goodsImport.getShopCatName());
            if (map != null) {
                shetuanGoodsDO.setShopCatItems(map.get("shopCatItems"));
                shetuanGoodsDO.setShopCatName(map.get("shopCatName"));
            }
        } else {
            shetuanGoodsDO.setShopCatItems(null);
            shetuanGoodsDO.setShopCatName(null);
        }
        return shetuanGoodsDO;
    }

    //设置商品分组
    private Map<String, String> getShetuanGoodsShopCat(ShetuanGoodsDO shetuanGoodsDO, String shopCatName) {
        Map<String, String> map = new HashMap<>();

        String[] shopCatNames = shopCatName.split(";");
        //商品分组的ID
        String newShopCatName = "";
        List<ShopCatItem> shopCatItems = new ArrayList<>();
        for (int i = 0; i < shopCatNames.length; i++) {
            String oneShopCatName = shopCatNames[i];
            //三级分组的分组名
            String catName = oneShopCatName.substring(oneShopCatName.lastIndexOf(">") + 1);
            ShopCatDO shopCat = shopCatManager.getByName(catName, shetuanGoodsDO.getSellerId());
            if (shopCat != null && shopCat.getShopCatId() != null) {
                newShopCatName = newShopCatName.concat(shopCat.getCatPathName() + ";");
                ShopCatItem shopCatItem = new ShopCatItem();
                BeanUtil.copyProperties(shopCat, shopCatItem);
                shopCatItems.add(shopCatItem);
            }
        }
        shetuanGoodsDO.setShopCatItems(JSON.toJSONString(shopCatItems));
        map.put("shopCatItems", JSON.toJSONString(shopCatItems));
        map.put("shopCatName", newShopCatName);

        return map;
    }

    //设置商品上下架状态
    private Integer getShetunGoodsStatus(String text) {
        if (text.equals(ShetuanGoodsStatusEnum.ON_LINE.getDescription())) {
            return ShetuanGoodsStatusEnum.ON_LINE.getIndex();
        } else if (text.equals(ShetuanGoodsStatusEnum.OFF_LINE.getDescription())) {
            return ShetuanGoodsStatusEnum.OFF_LINE.getIndex();
        } else {
            return ShetuanGoodsStatusEnum.CHECKED.getIndex();
        }
    }

}
